﻿using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Security.Cryptography;
using System.Text;
using System.Threading.Tasks;
using System.Configuration;

namespace RoccaStore.Utils
{
    public class SecurityUtils
    {
        public static string Encrypt(string data, string key)
        {
            // First we need to turn the input string into a byte array. 
            byte[] dataBytes = System.Text.Encoding.ASCII.GetBytes(data);
            byte[] dataKey = System.Text.Encoding.ASCII.GetBytes(key);

            PasswordDeriveBytes pdb = new PasswordDeriveBytes(Config.SecureKey, dataKey);

            byte[] encryptedData = Encrypt(dataBytes, 
                     pdb.GetBytes(32), pdb.GetBytes(16));

            return System.Web.HttpServerUtility.UrlTokenEncode(encryptedData);
        }

        public static byte[] Encrypt(byte[] clearData, byte[] Key, byte[] IV)
        {
            // Create a MemoryStream to accept the encrypted bytes 
            MemoryStream ms = new MemoryStream();
 
            Rijndael alg = Rijndael.Create();

            alg.Key = Key;
            alg.IV = IV;

            CryptoStream cs = new CryptoStream(ms,
               alg.CreateEncryptor(), CryptoStreamMode.Write);

            // Write the data and make it do the encryption 
            cs.Write(clearData, 0, clearData.Length);
            cs.Close();

            // Now get the encrypted data from the MemoryStream.
            // Some people make a mistake of using GetBuffer() here,
            // which is not the right way. 
            byte[] encryptedData = ms.ToArray();

            return encryptedData;
        }

        public static byte[] Decrypt(byte[] cipherData, byte[] Key, byte[] IV)
        {
            // Create a MemoryStream that is going to accept the
            // decrypted bytes 
            MemoryStream ms = new MemoryStream();

            Rijndael alg = Rijndael.Create();

            alg.Key = Key;
            alg.IV = IV;

            CryptoStream cs = new CryptoStream(ms,
                alg.CreateDecryptor(), CryptoStreamMode.Write);

            // Write the data and make it do the decryption 
            cs.Write(cipherData, 0, cipherData.Length);
            cs.Close();

            // Now get the decrypted data from the MemoryStream. 
            // Some people make a mistake of using GetBuffer() here,
            // which is not the right way. 
            byte[] decryptedData = ms.ToArray();

            return decryptedData;
        }

        public static string Decrypt(string data, string key)
        {
            byte[] dataBytes = System.Web.HttpServerUtility.UrlTokenDecode(data);
            byte[] keyBytes = System.Text.Encoding.ASCII.GetBytes(key);

            // Then, we need to turn the password into Key and IV 
            // We are using salt to make it harder to guess our key
            // using a dictionary attack - 
            // trying to guess a password by enumerating all possible words. 
            PasswordDeriveBytes pdb = new PasswordDeriveBytes(Config.SecureKey, keyBytes);

            byte[] decryptedData = Decrypt(dataBytes,
                pdb.GetBytes(32), pdb.GetBytes(16));

            return System.Text.Encoding.ASCII.GetString(decryptedData);
        }

        public static string CalculateMD5Hash(string input)
        {
            // step 1, calculate MD5 hash from input
            MD5 md5 = System.Security.Cryptography.MD5.Create();
            byte[] inputBytes = System.Text.Encoding.ASCII.GetBytes(input);
            byte[] hash = md5.ComputeHash(inputBytes);

            // step 2, convert byte array to hex string
            StringBuilder sb = new StringBuilder();
            for (int i = 0; i < hash.Length; i++)
            {
                sb.Append(hash[i].ToString("x2"));
            }
            return sb.ToString();
        }

        public static string HashEncrypt(string id)
        {
            string hash1 = SecurityUtils.CalculateMD5Hash(id);
            return SecurityUtils.CalculateMD5Hash(SecurityUtils.Encrypt(id, hash1));
        }
    }
}